package edu.uwm.cs552;

import java.util.Collection;
import java.util.Iterator;
import java.util.Random;

import javax.swing.JLabel;


/**
 * An immutable data class representing a transportation
 * goal of bringing a certain good to a certain city.
 */
public class Goal {

	private final Good good;
	private final HexCoordinate target;
	private final City city;
	private final int payoff;
	
	public Goal(Good g, HexCoordinate h, City c, int p) {
		good = g;
		target = h;
		city = c;
		payoff = p;
	}
	
	public Good getGood() { return good; }
	public HexCoordinate getTarget() { return target; }
	public City getCity() { return city; }
	public int getPayoff() { return payoff; }
	
	private static Random random = new Random();
	
	/**
	 * Return the nth element (0-based) of a collection
	 * @param T type of elements in collection
	 * @param c collection to look in
	 * @param n index
	 * @return nth element (0-based)
	 */
	private static <T> T nth(Collection<T> c, int n) {
		Iterator<T> it = c.iterator();
		for (int i=0; i < n; ++i) {
			it.next();
		}
		return it.next();
	}
	
	public static final int MAX_PAYOFF = 1000;
	public static final int MIN_PAYOFF = 5;
	public static final int VARIANCE = 5;
	
	/**
	 * Generate a random goal.  Payoff is closely related to the distance
	 * between the closest source and the target.  It is the distance
	 * plus a random value from [-VARIANCE/2,VARIANCE/2], but never less
	 * than MIN_PAYOFF.
	 * @param board game board, must not be null
	 * @return goal, never null
	 */
	public static Goal generate(HexBoard board) {
		Good[] allGoods = Good.allGoods();
		Collection<HexCoordinate> allLocations = board.allCityLocations();
		Good g = allGoods[random.nextInt(allGoods.length)];
		HexCoordinate t = nth(allLocations,random.nextInt(allLocations.size()));
		City c = board.getCity(t);
		int p = MAX_PAYOFF;
		for (HexCoordinate s : board.getSources(g)) {
			int d = s.distance(t) + random.nextInt(VARIANCE) - VARIANCE/2;
			if (d < p) p = d; 
		}
		if (p < MIN_PAYOFF) p = MIN_PAYOFF;
		return new Goal(g,t,c,p);
	}
	
	public JLabel asLabel() {
		JLabel result = new JLabel(toString());
		result.setIcon(good.getIcon());
		return result;
	}

	@Override
	public String toString() {
		return good.getName() + " to " + city.getName() + " for " + payoff;
	}
}
